﻿using IGeekFan.AspNetCore.Knife4jUI;
using Micro.Core.Packages;
using Micro.Extensions.Swagger.Filters;
using Micro.Modules.Abstractions;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Hosting;
using Microsoft.OpenApi.Models;

namespace Microsoft.Extensions.DependencyInjection
{
    [DependsOnPacks(typeof(APMPack))]
    public class SwaggerPack : BasePackage
    {

        public override PackLevel Level => PackLevel.Framework;
        public override int Order => 10;

        public override IServiceCollection AddServices(IServiceCollection services)
        {
            if (services.GetWebHostEnvironment().IsDevelopment())
            {
                //services.GetSingletonInstanceOrNull<IModuleCollection>();
                IModuleCollection modules = services.GetSingletonInstanceOrNull<IModuleCollection>();// services.BuildServiceProvider().GetService<IModuleCollection>()!;
                AddModuleSwagger(services, modules);
            }
            return base.AddServices(services);
        }


        public override void UsePack(WebApplication app)
        {
            if (app.Environment.IsDevelopment())
            {
                SwaggerConfigure(app);
            }
            //app.
            base.UsePack(app);
        }



        private void AddModuleSwagger(IServiceCollection services, IModuleCollection modules)
        {
            
            services.AddSwaggerGen(c =>
            {
                var hasDocs = false;
                if (modules != null)
                {
                    foreach (var module in modules)
                    {
                        c.SwaggerDoc(module.Code, new OpenApiInfo
                        {
                            Title = $"{module.Name}({module.Code})",
                            Version = module.Version,
                            Description = module.Description
                        });

                        //启用注解
                        c.EnableAnnotations();

                        //加载xml文档
                        foreach (var assembly in module.Context.GetAssemblies())
                        { 
                            var xmlPath = assembly.Location.Replace(".dll", ".xml", StringComparison.OrdinalIgnoreCase);
                            if (File.Exists(xmlPath))
                            {
                                c.IncludeXmlComments(xmlPath);
                            }
                        }
                        
                        hasDocs = true;
                    }
                }
                if (!hasDocs)
                {
                    c.SwaggerDoc("v1", new OpenApiInfo
                    {
                        Version = "v1",
                        Title = "默认API"
                    });
                }

                var securityScheme = new OpenApiSecurityScheme
                {
                    Description = "JWT认证请求头格式: \"Authorization: Bearer {token}\"",
                    Name = "Authorization",
                    In = ParameterLocation.Header,
                    Type = SecuritySchemeType.ApiKey,
                    Scheme = "Bearer"
                };

                //添加设置Token的按钮
                c.AddSecurityDefinition("Bearer", securityScheme);

                //添加Jwt验证设置
                c.AddSecurityRequirement(new OpenApiSecurityRequirement()
                {
                    {
                        new OpenApiSecurityScheme
                        {
                            Reference = new OpenApiReference
                            {
                                Type = ReferenceType.SecurityScheme,
                                Id = "Bearer"
                            },
                            Scheme = "oauth2",
                            Name = "Bearer",
                            In = ParameterLocation.Header,

                        },
                        new List<string>()
                    }
                });

                //描述信息处理
                c.DocumentFilter<DescriptionDocumentFilter>();
                //隐藏属性
                c.SchemaFilter<IgnorePropertySchemaFilter>();
                c.ResolveConflictingActions(apiDescriptions => apiDescriptions.First());
            });
            //使用JsonProperty别名
            services.AddSwaggerGenNewtonsoftSupport();
        }

        private void SwaggerConfigure(WebApplication app, string pathBase = null)
        {
            IModuleCollection modules = app.Services.GetService<IModuleCollection>()!;
            app.UseSwagger();
            app.UseSwaggerUI(c =>
            {
                c.RoutePrefix = "docs";
                if (modules == null || modules.Count == 0)
                {
                    c.SwaggerEndpoint("/swagger/v1/swagger.json", "默认API");
                    return;
                }
                var hasDocs = false;
                foreach (var module in modules)
                {
                    var url = $"{module.SwaggerPathBase}/swagger/{module.Code}/swagger.json";
                    url = pathBase.NotNull() ? $"{pathBase}{url}" : url;
                    c.SwaggerEndpoint(url, $"{module.Name}({module.Code})");
                    hasDocs = true;
                }
                if (!hasDocs)
                {
                    c.SwaggerEndpoint("/swagger/v1/swagger.json", "默认API");
                }
            });
            //swagger增强版
            app.UseKnife4UI(c =>
            {
                c.DocumentTitle = "KnifeUI.Swagger.Net 实例文档";
                c.RoutePrefix = "api-doc";

                if (modules == null || modules.Count == 0) return;

                foreach (var module in modules)
                {
                    var url = $"{module.SwaggerPathBase}/swagger/{module.Code}/swagger.json";
                    c.SwaggerEndpoint(pathBase.NotNull() ? $"{pathBase}{url}" : url, $"{module.Name}({module.Code})");
                }
            });
        }
    }
}